/*
Copyright 2009 David Revell

This file is part of SwiFTP.

SwiFTP is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

SwiFTP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with SwiFTP.  If not, see <http://www.gnu.org/licenses/>.
*/


package lfr.ustc.ftp;

/**
 * ����Ϊ����STOR��APPE�ĸ��࣬
 */
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

abstract public class CmdStorAndAppe extends CmdManager {
	public CmdStorAndAppe(SocketManager sessionThread, String input) {
		super(sessionThread);
	}
	public void doStorOrAppe(String param, boolean append) {
		File storeFile = inputPathToChrootedFile(sessionThread.getWorkingDir(),
				param);
		String errString = null;
		FileOutputStream out = null;
		storing: {
			if (violatesChroot(storeFile)) {
				errString = "550 Invalid name or chroot violation\r\n";
				break storing;
			}
			if (storeFile.isDirectory()) {
				errString = "451 Can't overwrite a directory\r\n";
				break storing;
			}
			try {
				if (storeFile.exists()) {
					if (!append) {
						if (!storeFile.delete()) {
							errString = "451 Couldn't truncate file\r\n";
							break storing;
						}
					
					}
				}
				out = new FileOutputStream(storeFile, append);
			} catch (FileNotFoundException e) {
				try {
					errString = "451 Couldn't open file \"" + param
							+ "\" aka \"" + storeFile.getCanonicalPath()
							+ "\" for writing\r\n";
				} catch (IOException io_e) {
					errString = "451 Couldn't open file, nested exception\r\n";
				}
				break storing;
			}
			if (!sessionThread.startUsingDataSocket()) {
				errString = "425 Couldn't open data socket\r\n";
				break storing;
			}
			sessionThread.sendInfo("150 Data socket ready\r\n");
			byte[] buffer = new byte[10240];
			int numRead;
			while (true) {
				switch (numRead = sessionThread.receiveFromDataSocket(buffer)) {
				case -1:
					break storing;
				case 0:
					errString = "426 Couldn't receive data\r\n";
					break storing;
				case -2:
					errString = "425 Could not connect data socket\r\n";
					break storing;
				default:
					try {
						if (sessionThread.transmitType.equals("BINARY")) {
							out.write(buffer, 0, numRead);
						} else {
							int startPos = 0, endPos;
							for (endPos = 0; endPos < numRead; endPos++) {
								if (buffer[endPos] == '\r') {
									out.write(buffer, startPos, endPos
											- startPos);
									startPos = endPos + 1;
								}
							}
							if (startPos < numRead) {
								out.write(buffer, startPos, endPos - startPos);
							}
						}

						out.flush();

					} catch (IOException e) {
						errString = "451 File IO problem. Device might be full.\r\n";
						break storing;
					}
					break;
				}
			}
		}
		try {
			if (out != null) {
				out.close();
			}
		} catch (IOException e) {
		}

		if (errString != null) {
			sessionThread.sendInfo(errString);
		} else {
			sessionThread.sendInfo("226 Transmission complete\r\n");
		}
		sessionThread.closeDataSocket();
	}
}
